package org.test.jiazi_1.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.test.jiazi_1.mapper.FitnessMapper;
import org.test.jiazi_1.mapper.ScoresMapper;
import org.test.jiazi_1.pojo.entity.Fitness;
import org.test.jiazi_1.pojo.entity.Scores;
import org.test.jiazi_1.service.FitnessService;
import org.test.jiazi_1.service.ScoresService;

import java.util.List;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import static org.test.jiazi_1.common.constant.GradeConstant.BMI_WEIGHT;
import static org.test.jiazi_1.common.constant.GradeConstant.EIGHT_HUNDRED_METER_RUN_OR_ONE_THOUSAND_METER_RUN_WEIGHT;
import static org.test.jiazi_1.common.constant.GradeConstant.FIFTY_METER_RUN_WEIGHT;
import static org.test.jiazi_1.common.constant.GradeConstant.LUNG_CAPACITY_WEIGHT;
import static org.test.jiazi_1.common.constant.GradeConstant.PULL_UPS_OR_ONE_MINUTE_SIT_UPS_WEIGHT;
import static org.test.jiazi_1.common.constant.GradeConstant.SIT_AND_REACH_WEIGHT;
import static org.test.jiazi_1.common.constant.GradeConstant.STANDING_LONG_JUMP_WEIGHT;
import static org.test.jiazi_1.common.utils.ScoreCalculator.calculateBMIScore;
import static org.test.jiazi_1.common.utils.ScoreCalculator.calculateEightHundredMeterRunScore;
import static org.test.jiazi_1.common.utils.ScoreCalculator.calculateFiftyMeterRunScore;
import static org.test.jiazi_1.common.utils.ScoreCalculator.calculateLungCapacityScore;
import static org.test.jiazi_1.common.utils.ScoreCalculator.calculateOneMinuteSitUpsScore;
import static org.test.jiazi_1.common.utils.ScoreCalculator.calculateOneThousandMeterRunScore;
import static org.test.jiazi_1.common.utils.ScoreCalculator.calculatePullUpsScore;
import static org.test.jiazi_1.common.utils.ScoreCalculator.calculateSitAndReachScore;
import static org.test.jiazi_1.common.utils.ScoreCalculator.calculateStandingLongJumpScore;

/**
 * 体测评分表(Scores)表服务实现类
 *
 * @author 2251300222 唐文涛
 * @since 2025-10-24 13:33:08
 */
@Slf4j
@Service("scoresService")
public class ScoresServiceImpl extends ServiceImpl<ScoresMapper, Scores> implements ScoresService {


    @Resource
    private FitnessService fitnessService;


    @Transactional(rollbackFor = Exception.class)
    public void calculateScores(Integer courseId) {
        List<Scores> scoresList = fitnessService.getListByCourseId(courseId)
                .stream()
                .map(this::buildScores)
                .collect(Collectors.toList());

        this.saveBatch(scoresList);
    }

    private Scores buildScores(Fitness fitness) {
        // 构建Scores对象的逻辑
        boolean oneOrTwoGrade = fitnessService.getGrade(fitness);
        boolean male = fitnessService.getMale(fitness);
        // 计算详细的体测评分
        return calculateScoresDetail(fitness, oneOrTwoGrade, male);

    }

    private void processLevels(Scores scores) {
        scores.setRun800mLevel(getLevel(scores.getRun800mScore()));
        scores.setRun50mLevel(getLevel(scores.getRun50mScore()));
        scores.setLongJumpLevel(getLevel(scores.getLongJumpScore()));
        scores.setSitAndReachLevel(getLevel(scores.getSitAndReachScore()));
        scores.setWeightLevel(getLevel(scores.getWeightScore()));
        scores.setVitalCapacityLevel(getLevel(scores.getVitalCapacityScore()));
        scores.setRun1000mLevel(getLevel(scores.getRun1000mScore()));
        scores.setPullUpsLevel(getLevel(scores.getPullUpsScore()));
        scores.setTotalLevel(getLevel2(scores.getTotalScore()));
    }

    public static String getLevel(Integer score) {
        if (score >= 90) {
            return "优秀";
        } else if (score >= 80) {
            return "良好";
        } else if (score >= 60) {
            return "及格";
        } else {
            return "不及格";
        }
    }
    public static String getLevel2(Double score) {
        if (score >= 90) {
            return "优秀";
        } else if (score >= 80) {
            return "良好";
        } else if (score >= 60) {
            return "及格";
        } else {
            return "不及格";
        }
    }
    private Scores calculateScoresDetail(Fitness fitness, boolean oneOrTwoGrade, boolean male) {
        Scores scores = new Scores();
        if (male) {
            scores.setRun1000mScore(calculateOneThousandMeterRunScore(fitness.getRun1000m(), oneOrTwoGrade));
            scores.setPullUpsScore(calculatePullUpsScore(fitness.getPullUps(), oneOrTwoGrade));
        } else {
            scores.setRun800mScore(calculateEightHundredMeterRunScore(fitness.getRun800m(), oneOrTwoGrade));
            scores.setSitUpsScore(calculateOneMinuteSitUpsScore(fitness.getSitUps(), oneOrTwoGrade));
        }
        scores.setWeightScore(calculateBMIScore(fitness.getHeight(), fitness.getWeight(), male));
        scores.setVitalCapacityScore(calculateLungCapacityScore(fitness.getVitalCapacity(), male, oneOrTwoGrade));
        scores.setRun50mScore(calculateFiftyMeterRunScore(fitness.getRun50m(), male, oneOrTwoGrade));
        scores.setLongJumpScore(calculateStandingLongJumpScore(fitness.getLongJump(), male, oneOrTwoGrade));
        scores.setSitAndReachScore(calculateSitAndReachScore(fitness.getSitAndReach(), male, oneOrTwoGrade));

        //计算附加分
        scores.setBonusScore(calculateBonusScore(scores, male));
        //计算标准分
        scores.setStandardScore(calculateStandardScore(scores, male));
        //计算总分
        scores.setTotalScore(scores.getStandardScore() + scores.getBonusScore());
        //计算等级
        processLevels(scores);

        return scores;
    }

    private Double calculateStandardScore(Scores scores, boolean male) {
        double standardScore = scores.getVitalCapacityScore() * LUNG_CAPACITY_WEIGHT +
                scores.getRun50mScore() * FIFTY_METER_RUN_WEIGHT +
                scores.getLongJumpScore() * STANDING_LONG_JUMP_WEIGHT +
                scores.getSitAndReachScore() * SIT_AND_REACH_WEIGHT +
                scores.getWeightScore() * BMI_WEIGHT;
        if (male) {
            standardScore += (scores.getRun1000mScore() * EIGHT_HUNDRED_METER_RUN_OR_ONE_THOUSAND_METER_RUN_WEIGHT) +
                    (scores.getPullUpsScore() * PULL_UPS_OR_ONE_MINUTE_SIT_UPS_WEIGHT);
        } else {
            standardScore += (scores.getRun800mScore() * EIGHT_HUNDRED_METER_RUN_OR_ONE_THOUSAND_METER_RUN_WEIGHT) +
                    (scores.getSitUpsScore() * PULL_UPS_OR_ONE_MINUTE_SIT_UPS_WEIGHT);
        }
        return standardScore;

    }


    private Integer calculateBonusScore(Scores scores, boolean male) {
        int bonus = 0;
        if (male) {
            bonus += setExtraScoreIfExceed(scores.getRun1000mScore(), scores::setRun1000mBonus,
                    scores::setRun1000mScore);
            bonus += setExtraScoreIfExceed(scores.getPullUpsScore(), scores::setPullUpsBonus, scores::setPullUpsScore);
        }
        // 处理女性专属附加分
        else {
            bonus += setExtraScoreIfExceed(scores.getRun800mScore(), scores::setRun800mBonus, scores::setRun800mScore);
            bonus += setExtraScoreIfExceed(scores.getSitUpsScore(), scores::setSitUpsBonus, scores::setSitUpsScore);

        }
        return bonus;
    }


    public static Integer setExtraScoreIfExceed(Integer baseScore, Consumer<Integer> setter,
                                                Consumer<Integer> setter2) {

        if (baseScore != null && baseScore > 100) {
            setter.accept(baseScore - 100);
            setter2.accept(100);
            return baseScore - 100;
        } else {
            setter.accept(0); // 或保持原值不变
            return 0;
        }
    }
}
